/*

Arduino Countdown Timer
by Randy Sarafan - 2013

Uses two 7-segment displays to countdown from 99 to 0. When the timer reaches zero, the display flashes and a piezo beeps.

- To start the timer press the button. 

- To pause the timer, press the button again.

- To reset before reaching 0, press the button 3 times quickly in under 1-second. When timer reaches 0, press once to reset.

For more information visit:
http://www.instructables.com/id/Arduino-Countdown-Timer/


This code incorporates Arduino State Change Detection and Debouncing example code by David A. Mellis, Limor Fried, and Tom Igoe. 

This code is in the Public Domain. 

*/



// The number of the pushbutton pin
const int buttonPin = 12;     

// 7-segment identifier variables
int leftnumber;
int rightnumber;

// Variables for the current and the previous reading from the pushbutton pin
int buttonState;             
int lastButtonState = 0; 

// Additional variable to keep track of the previous button press state.
// This one only keeps track of the state of the button when there is a 
// debounce delay event.
int previousState;

// Tracks the last time the output pin was toggled
long lastDebounceTime = 0;  

 // The debounce time; increase if the button is registering a single press more than once
long debounceDelay = 20;   

// Variable for counting the number of times the button has been pressed.
int buttonPushCounter;

// This variable gets toggled either high or low each time the button is pressed. 
// In other words, this variable changes states with each button press.
bool pressed = true;



int buttonpress;

void setup() {    

  // Set 7-segement outputs  
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  
  // Set buzzer output
  pinMode(11, OUTPUT);
  
  // Set pushbutton input
  pinMode(buttonPin, INPUT);

}

void loop() {
  
  for (int i = 0; i < 10; i++) {
    // Counts down the left digit by 10
    leftnumber = 9 - i;
    
    for (int x = 0; x < 10; x++) {
      // Counts down the right digit.
      // Since this is inside the other loop,
      // it counts down by 10 ten times
      rightnumber = 9 - x;
      
      // This loop displays the digits and checks the button
      // Decrease this number to make it go faster
      for (int y = 0; y < 50; y) {
        
        // Take a button reading
        int reading = digitalRead(buttonPin);
        
        // check to see if you just pressed the button
        // (i.e. the input went from LOW to HIGH),  and you've waited
        // long enough since the last press to ignore any noise:  
        
        // If the state of the the switch has changed, due to being 
        // pressed or a false contact, then reset the debounce timer
        if (reading != lastButtonState) {
          lastDebounceTime = millis();
        } 
        
        // If the current reading is beyond the debounce delay
        // set the button state to the current reading
        if ((millis() - lastDebounceTime) > debounceDelay) {
          buttonState = reading;
        }
        
        
        // If the current state and the previous state do not match
        // and the current state indicates that the button is being pressed
        // then flip the state of the "pressed" variable (to true or false)
        // and increase the button push counter
        if (buttonState != previousState) {
          if(buttonState == 1){
            pressed = !pressed;
            buttonPushCounter++;
          }
        }
        
        // If the state of the button press is true
        // then the display is paused and it stops counting
        if (pressed == true){
            
            // Displays the left digit
            digitalWrite(9, 1);
            digitalWrite(10, 0);
            lightUpDigit(leftnumber);
            delay(10);
            
            // Displays the right digit
            digitalWrite(9, 0);
            digitalWrite(10, 1);
            lightUpDigit(rightnumber);
            delay(10);
          }
          
        // Otherwise, if the state is not true
        // the display resumes displaying the countdown
        else{
            digitalWrite(9, 1);
            digitalWrite(10, 0);
            lightUpDigit(leftnumber);
            delay(10);
            
            digitalWrite(9, 0);
            digitalWrite(10, 1);
            lightUpDigit(rightnumber);
            delay(10);
            y = y + 1;
          }
            
       
        
        // Update the previousState variable for the next loop
        previousState = buttonState; 
         
        // Update the lastButtonState variable for the next loop
        lastButtonState = reading;
        
        // If both digits equal zero, stop the counter, flash 00 and beep
        while(leftnumber == 0 && rightnumber == 0){
           
          // Calls timesup routine and runs until the button is pressed and timer reset
          timesUp();
        }
        
        
        // If the button is pressed 3 times in under a second
        // reset the program
        if (buttonPushCounter > 2) {
          buttonPushCounter = 0;
          return;
        }
      }
      
      // Resets the button press count after 1 second
      buttonPushCounter = 0;
    }
  }
}


// This function runs over and over when the time runs out
// Only pressing the red button makes this stop
void timesUp(){
  
  // Beep on
  analogWrite(11, 20);
  
  // Display "00" 1/2 second
  for (int z = 0; z < 25; z++) {
    digitalWrite(9, 1);
    digitalWrite(10, 0);
    lightUpDigit(0);
    delay(10);
            
    digitalWrite(9, 0);
    digitalWrite(10, 1);
    lightUpDigit(0);
    delay(10);
    
    // Reset the counter if the button is pressed
    // and disable the display and beep
    if(digitalRead(buttonPin) == 1){
       pressed = true;
       leftnumber = 9;
       rightnumber = 9;
       analogWrite(11, 0);
       digitalWrite(9, 1);
       digitalWrite(10, 1);
       delay(2000);
       return;
     } 
   }
   
   // Beep off
   analogWrite(11, 0);
   
   // Display off 1/2 second
   for (int z = 0; z < 25; z++) {

     digitalWrite(9, 1);
     digitalWrite(10, 0);
     lightUpDigit(10);
     delay(10);
            
     digitalWrite(9, 0);
     digitalWrite(10, 1);
     lightUpDigit(10);
     delay(10);
    
     // Reset the counter if the button is pressed
     if(digitalRead(buttonPin) == 1){
       pressed = true;
       leftnumber = 9;
       rightnumber = 9;
       delay(2000);
       return;
      } 
   } 
}



// This function has a case statement 
// which sets the pins high or low,
// and displays each of the digits.

void lightUpDigit(int DisplayNumber) {
  
  switch (DisplayNumber){
    case 0:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 0);
    digitalWrite(7, 1);
    digitalWrite(8, 1);
    break;

    case 1:
    digitalWrite(2, 1);
    digitalWrite(3, 0);
    digitalWrite(4, 1);
    digitalWrite(5, 0);
    digitalWrite(6, 0);
    digitalWrite(7, 0);
    digitalWrite(8, 0);
    break;
    
    
    case 2:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 0);
    digitalWrite(5, 0);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 1);
    break;
    
    case 3:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 0);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 0);
    break;
    
    case 4:
    digitalWrite(2, 1);
    digitalWrite(3, 0);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 0);
    digitalWrite(8, 0);
    break;
    
    case 5:
    digitalWrite(2, 0);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 0);
    break;
    
    case 6:
    digitalWrite(2, 0);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 1);
    break;
    
    case 7:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 0);
    digitalWrite(6, 0);
    digitalWrite(7, 0);
    digitalWrite(8, 0);
    break;
    
    case 8:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 1);
    break;
    
    case 9:
    digitalWrite(2, 1);
    digitalWrite(3, 1);
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 0);
    break;
    
    case 10:
    digitalWrite(2, 0);
    digitalWrite(3, 0);
    digitalWrite(4, 0);
    digitalWrite(5, 0);
    digitalWrite(6, 0);
    digitalWrite(7, 0);
    digitalWrite(8, 0);
    break;
  }
}
